
from Tkinter import *
from ttk import *
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg


import tkMessageBox
import Tape
import TuringMachine
import Transition
import matplotlib.pyplot as plt
import networkx as nx







class Interface:
    
    def __init__(self, root):
        self.container=Frame(root)
        self.container.pack()
        self.rules = Transition.Transition()
        self.finalStates = []
        #Frame top
        self.high_container=Frame(self.container,  borderwidth = 1,  relief = RIDGE,)
        self.high_container.pack(side = TOP, fill =BOTH ,expand=NO)
        
        #frame bottom
        self.bottom_container=Frame(self.container,borderwidth = 1, relief = RIDGE,)
        self.bottom_container.pack(side = BOTTOM, fill = X)
        
        #frame tape
        self.tape=Frame(self.high_container)
        self.tape.pack(side=BOTTOM ,fill=BOTH)
        
        
        self.w3=Label(self.tape, text="Insert the tape input:", width=20)
        self.w3.pack(side=LEFT)
        self.tapeInputT=Entry(self.tape)
        self.tapeInputT.insert("0", "abbb|B|")
        self.tapeInputT.pack(side=LEFT)
     





        self.addStateFrame=Frame(self.high_container)
        self.addStateFrame.pack()
        

        Label(self.addStateFrame, text="new state").pack(side=TOP)
        
        self.newStateEntry=Entry(self.addStateFrame, width=5)
        self.newStateEntry.pack( side=LEFT)
        
        self.finalStateBool = BooleanVar()
        Checkbutton(self.addStateFrame, text="Final state", variable= self.finalStateBool).pack(side=LEFT)
        
        self.addState=Button(self.addStateFrame, text="+", command=self.addState, width=5)
        self.addState.pack()




        #frame top left
        self.rulesFrame=Frame(self.high_container)
        self.rulesFrame.pack(side=LEFT)
        

        Label(self.rulesFrame, text="(cs,cv)->(ns,nv,m)").pack(side=TOP)
        
        
        
        self.cs=Entry(self.rulesFrame, width=5)
        self.cs.pack( side=LEFT)
        self.cv=Entry(self.rulesFrame, width=5)
        self.cv.pack( side=LEFT)
        self.ns=Entry(self.rulesFrame, width=5)
        self.ns.pack( side=LEFT)
        self.nv=Entry(self.rulesFrame, width=5)
        self.nv.pack( side=LEFT)
        self.m=Entry(self.rulesFrame, width=5)
        self.m.pack( side=LEFT)
        
        self.addRule=Button(self.rulesFrame, text="+", command=self.addRule, width=5)
        self.addRule.pack(side=BOTTOM)
        #frame top right
        self.inout=Frame(self.high_container)
        self.inout.pack(side=LEFT, fill=X)
        
        #frame right top
        self.input=Frame(self.inout)
        self.input.pack(side=TOP)
        
        self.w1=Label(self.input, text="Insert here initial state:")
        self.w1.pack(side = TOP)
        self.initialState=StringVar()
        self.box = Combobox(self.input, textvariable=self.initialState, state='readonly')
        self.box.pack()
        


#         self.initialStateT=Entry(self.input)
#         self.initialStateT.insert("0", "s")
#         self.initialStateT.pack()
        
        #frame right bottom
        self.out=Frame(self.inout)
        self.out.pack(side=BOTTOM)
        
        
        
        
        
        self.w3=Label(self.out, text="Insert here Blank Symbol:")
        self.w3.pack(side = TOP)
        
        vcmd = (root.register(self.validateBlank), '%P')
        self.blanckSymbolT=Entry(self.out,validate = "key",validatecommand=vcmd)
        
        self.blanckSymbolT.pack()
        

        
        
        
        b=Button(self.tape, text="create machine", command=self.createMachineEvent)
        #b.bind("<ButtonRelease--1>", self.createMachineEvent)
        b.pack()
        
        
        
#         f = plt.figure(figsize=(5,4))
#         a = f.add_subplot(111)
#         plt.axis('off')

# the networkx part
        self.G = nx.MultiDiGraph()
#         nx.draw_networkx(self.G, pos=nx.spring_layout(self.G))
    
#         canvas = FigureCanvasTkAgg(f, master=root)
#         canvas.show()
#         canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
        
        self.labelframel = LabelFrame(self.bottom_container, text="left part")
        self.labelframel.pack(side=LEFT)
        self.leftList=StringVar()
        left = Label(self.labelframel, text="leftList", textvariable=self.leftList)
        left.pack()
        
       
        self.labelframec = LabelFrame(self.bottom_container,text="current Value")
        self.labelframec.pack(side=LEFT)
        
        self.currentValue=StringVar()
        center = Label(self.labelframec, textvariable=self.currentValue)
        center.pack()
        
        self.rightList=StringVar()
        self.labelframer = LabelFrame(self.bottom_container, text="right list")
        self.labelframer.pack(side=LEFT)
        
        right = Label(self.labelframer, textvariable=self.rightList)
        right.pack()
        
        self.nextButton=Button(self.bottom_container, text="nextStep", command=self.machineStep)
        self.nextButton.state(['disabled'])
        self.nextButton.pack(side=BOTTOM)
        
        
        
    def validateBlank(self, P):
        return len(P)<=1
        
    def createMachineEvent(self):
        if not len(self.tapeInputT.get().split('|'))==3:
            tkMessageBox.showerror('Machine creation error',"Tape not correct" )
            return
        if not self.rules:
            tkMessageBox.showerror('Machine creation error',"Rules not correct" )
            return
        if not self.box.get():
            tkMessageBox.showerror('Machine creation error',"Initial State not selected" )
            return

        self.myMachine=TuringMachine.TuringMachine(self.rules, self.tapeInputT.get(),self.blanckSymbolT.get(),self.initialState.get(), self.finalStates)
        #self.t=Tape.Tape(self.blanckSymbolT, self.tapeInputT.get());
        self.rightList.set(''.join(self.myMachine.tape.rightList[::-1]))
        self.currentValue.set(self.myMachine.tape.currentValue)
        self.leftList.set(''.join(self.myMachine.tape.leftList))
        self.nextButton['state']='!disabled'

        
    def addState(self):
        newState =self.newStateEntry.get()
        if newState and newState not in self.rules:
            self.rules[newState] = {}
            if self.finalStateBool.get():
                self.finalStates.append(newState)
            self.finalStateBool.set(False)
            self.newStateEntry.delete(0)
            self.G.add_node(newState)
            self.box['values'] = self.rules.keys()    
            print self.box.get()         
            plt.clf()
            nx.draw(self.G)
            nx.draw_networkx_edge_labels(self.G, nx.spring_layout(self.G))
            plt.show()

            
    
    def addRule(self):
        cs=self.cs.get()
        ns=self.ns.get()
        if cs and self.cv.get() and ns and self.nv.get() and self.m.get():
            if cs not in self.rules:
                return
            plt.clf()
            self.rules[cs][self.cv.get()]=(ns,self.nv.get(),int(self.m.get()))
            
            self.G.add_edge(cs,ns, instruction=self.cv.get(), replace=self.nv.get(), move=int(self.m.get() ))
           
            nx.draw(self.G)
            
            nx.draw_networkx_edge_labels(self.G, nx.spring_layout(self.G))
            
            plt.show()
            print(self.rules)
        
    def machineStep(self):
        try:
            self.myMachine.next()
            self.rightList.set(''.join(self.myMachine.tape.rightList[::-1]))
            self.currentValue.set(self.myMachine.tape.currentValue)
            self.leftList.set(''.join(self.myMachine.tape.leftList))
        except TuringMachine.MachineFinished:
            tkMessageBox.showinfo('Machine Termination',"successful" )
            self.nextButton['state']='disabled'
        except TuringMachine.MachineStuck:
            tkMessageBox.showinfo('Machine Termination',"Machine stuck" )
            self.nextButton['state']='disabled'
            
                                
        
        
        
        
        
    

 
        
        
root = Tk()
interface = Interface(root)
root.mainloop()